//
// Created by Wei on 2022/5/15.
//

#ifndef B_PLUS_DB_PAGE_H
#define B_PLUS_DB_PAGE_H

#include <vector>
#include "file_header.h"
#include "page_header.h"
#include "compact_header.h"
#include "compact_data.h"
#include "compact_dir.h"
#include "compact_only_id.h"

#define FREE_DATA_SIZE 4046
#define CONST_DATA_SIZE 26
#define infimum_offset 0
#define supermum_offset 13
#define data_offset 26

//26 bytes
struct INFIMUM_PART {
    COMPACT_HEADER header{};
    const unsigned char infimum[8] = {'i', 'n', 'f', 'i', 'm', 'u', 'm', 0};
};
struct SUPER_PART {
    COMPACT_HEADER header{};
    const unsigned char supermum[8] = {'s', 'u', 'p', 'e', 'r', 'm', 'u', 'm'};
};

//4K
class PAGE {
public:
    FILE_HEADER file_header{};//文件头 24 bytes
    PAGE_HEADER page_header{};//页头 40 bytes
    //数据开始下表
    unsigned char page_data[CONST_DATA_SIZE + FREE_DATA_SIZE]{};
private:
    static void init(PAGE *);

    //查找插入位置的前驱节点
    COMPACT_HEADER *findInsertPrev(const COMPACT_ONLY_ID *compact, unsigned short *preIndex);

    //页尾部插入
    int insertAtEnd(const COMPACT_ONLY_ID *compact);

    //回收空间插入
    int insertAtPieces(const COMPACT_ONLY_ID *compact);

    //分裂但不插入，返回0对应id插入位置在本页，返回1在下一页，返回-1上一页，还没做
    int split(unsigned int id);

    //插入目录项记录，通常只有内部调用
    int insert(COMPACT_DIR *compact);

    PAGE *searchNear(unsigned int id);

    void updateMinId(unsigned int id);

    unsigned int getMinId();

    int insertWithoutLock(COMPACT_DIR *compact);

    int insertWithoutLock(COMPACT_DATA *compact);

public:
    PAGE(unsigned int page_offset, unsigned int prev, unsigned int next, unsigned int page_type);

    PAGE(unsigned int page_offset);

    PAGE();

    /**
     * 插入单条记录
     * @param compact
     * @return 0成功 -1主键冲突 -2此页面初始化错误
     */
    int insert(COMPACT_DATA *compact);

    /**
     * 单条记录查询
     * @param id
     * @return
     */
    COMPACT_DATA *search(unsigned int id);

    /**
     * 范围查询
     * @param start
     * @param end
     * @return
     */
    std::vector<COMPACT_DATA> search(unsigned int start, unsigned int end);

    /**
     * 范围查询
     * @param start
     * @param end
     * @return
     */
    int search(unsigned int start, unsigned int end, COMPACT_DATA **receptor);

    size_t getPageNo();

    void setPageNo(size_t page_no);

};

#endif //B_PLUS_DB_PAGE_H
